package com.qf.config;


import com.qf.constant.RabbitMQConstants;
import org.springframework.amqp.core.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.lang.Nullable;
import org.springframework.web.bind.annotation.RequestParam;

import java.util.HashMap;
import java.util.Map;


@Configuration
public class RabbitMQConfig {

    // TOPIC_SMS_SEND_LOG的交换机
    @Bean
    public Exchange sendLogExchange() {
        return ExchangeBuilder.topicExchange(RabbitMQConstants.TOPIC_SMS_SEND_LOG + "_exchange").build();
    }

    // TOPIC_SMS_SEND_LOG的队列
    @Bean
    public Queue sendLogQueue() {
        return QueueBuilder.durable(RabbitMQConstants.TOPIC_SMS_SEND_LOG).build();
    }

    // TOPIC_SMS_SEND_LOG的绑定方式
    @Bean
    public Binding sendLogBinding(Queue sendLogQueue, Exchange sendLogExchange) {
        return BindingBuilder.bind(sendLogQueue).to(sendLogExchange).with(RabbitMQConstants.BINDING).noargs();
    }

    // TOPIC_PUSH_SMS_REPORT的交换机
    @Bean
    public Exchange pushSmsReportExchange() {
        return ExchangeBuilder.topicExchange(RabbitMQConstants.TOPIC_PUSH_SMS_REPORT + "_exchange").build();
    }

    // TOPIC_PUSH_SMS_REPORT的队列
    @Bean
    public Queue pushSmsReportQueue() {
        return QueueBuilder.durable(RabbitMQConstants.TOPIC_PUSH_SMS_REPORT).build();
    }

    // TOPIC_PUSH_SMS_REPORT的绑定方式
    @Bean
    public Binding pushSmsReportBinding(Queue pushSmsReportQueue, Exchange pushSmsReportExchange) {
        return BindingBuilder.bind(pushSmsReportQueue).to(pushSmsReportExchange).with(RabbitMQConstants.BINDING).noargs();
    }

    ///////////////////////////////下面是延迟消息的配置////////////////////////////////////////////////////////////////////
    /**
     * 向消费者推送报告的时候
     *   由于JD的消费者未接收到此报告、1m 3m 5m 间隔情况下 多次发送报告  直到JD消费者回复我们success
     *
     *   间隔发送情况：使用的RabbitMQ的延迟消息来完成的，而不是定时器
     *   11：42 ~ 11：43接收到消息  再次发送消息  依此类推
     */
    /**
     * 基于插件的延迟消息：
     * 交换机（延迟）  --》 routingKey --> 队列
     */
    public static final String EXCHANGE_DELAYED = "exchange_delayed";
    public static final String QUEUE_DELAYED = "queue_delayed";
    public static final String ROUTING_KEY_DELAYED = "#";

    /**
     * 一个水壶：玻璃的水壶      水壶有水：白开水
     * 保存延迟消息的交换机就被创建出来的
     *
     * @return
     */
    @Bean //SpringIOC将下面方法执行一次 并将Exchange返回保存在SpringIOC容器中  加入到Spring管理中
    public Exchange delayedExchange() {//被执行二次
        Map<String, Object> args = new HashMap<>();
        // direct,fanout,topic,headers
        // 指定当前延迟交换机的具体路由类型
        args.put("x-delayed-type", "topic");//交换机本身的类型 主题类型
        //自定义交换机  ： 构造器第二个参数 ：交换机中保存的消息是什么类型的   x-delayed-message
        CustomExchange customExchange = new CustomExchange(
                EXCHANGE_DELAYED, "x-delayed-message", true, false, args);
        return customExchange;
    }

    //队列
    @Bean
    public Queue delayedQueue() {//被执行1次
        return QueueBuilder.durable(QUEUE_DELAYED).build();
    }

    //绑定
    @Bean  //SpringIOC将下面方法执行一次 并将Exchange返回保存在SpringIOC容器中  加入到Spring管理中
    public Binding bindingDelayedExchangeToDelayedQueue(Queue delayedQueue, Exchange delayedExchange) {
        return BindingBuilder.bind(delayedQueue).to(delayedExchange).with(ROUTING_KEY_DELAYED).noargs();
    }

    ///////////////////////基于死信的//////////////////////////////////////
    public static final String EXCHANGE_DEAD_LETTER = "exchange_dead_letter";
    public static final String QUEUE_DEAD_LETTER = "queue_dead_letter";
    public static final String ROUTING_KEY_DEAD_LETTER = "routing_key_dead_letter";
    public static final String QUEUE_NORMAL = "queue_normal";
    public static final String ROUTING_KEY_NORMAL = "routing_key_normal";

    //死信交换机 正常交换机  合并
    @Bean
    public Exchange deadLetterExchange() {
        return ExchangeBuilder.directExchange(EXCHANGE_DEAD_LETTER).build();
    }

    //正常队列
    @Bean
    public Queue normalQueue() {
        return QueueBuilder.durable(QUEUE_NORMAL).build();
    }
    //死信队列
    //public Queue(
    // String name,
    // boolean durable,
    // boolean exclusive,
    // boolean autoDelete,
    // @Nullable Map<String, Object> arguments) {
    @Bean
    public Queue deadLetterQueue() {
        Map<String, Object> arguments = new HashMap<>();
        //x-message-ttl 消息死多久：《过期时间》
        //20s 全局设置过期时间   发消息的人设置局部过期时间  二者同时存在局部过期时间优先级最高
        arguments.put("x-message-ttl",20000);//托底设置： 发消息的人没有设置
        //过期转发到哪个死信交接机
        arguments.put("x-dead-letter-exchange",EXCHANGE_DEAD_LETTER);
        //过期转发到哪个死信routing key
        arguments.put("x-dead-letter-routing-key",ROUTING_KEY_DEAD_LETTER);
        return new Queue(QUEUE_DEAD_LETTER, true,
                true, false,arguments);
    }

    //绑定
    @Bean
    public Binding bindingDeadLetterExchangeToDeadLetterQueue(
            Exchange deadLetterExchange, Queue deadLetterQueue
    ){
        return BindingBuilder.bind(deadLetterQueue).to(deadLetterExchange)
                .with(ROUTING_KEY_NORMAL).noargs();
    }
    @Bean
    public Binding bindingDeadLetterExchangeToNormalQueue(
            Exchange deadLetterExchange,Queue normalQueue
    ){
        return BindingBuilder.bind(normalQueue).to(deadLetterExchange)
                .with(ROUTING_KEY_DEAD_LETTER).noargs();
    }
}
